﻿#include "projHeader.h"

////////////////////Потоки Moldovich/////////////////////

HANDLE hThreadTrain1 = 0,hThreadTrain2 = 0,hThreadTrain3 = 0,hThreadTrain4 = 0, hThreadSound_Metro = 0 ; // Хедеры потоков поездов
int ThreadTrain1 = 0,ThreadTrain2 = 0;
LPDWORD lpExitCode1, lpExitCode2;

extern int flag_suspended = 0; //флаг приостановки потоков поездов метро
BOOL SoundStatus;

DWORD WINAPI Sound_Metro(void*p) //запускает звуки при спуске в метро
{
	srand(time(0));
	int Variant = rand()%8;
	GotoXY(0,0);
	cout << "Variant =  " << Variant;
	Sleep(997);
	switch (Variant)
	{
	case 0: SoundStatus = PlaySoundA("sound\\zvuk_metro_3.wav", NULL, SND_ASYNC);break;
	case 1: SoundStatus = PlaySoundA("sound\\ostorojno_dveri_zakrsya.wav", NULL, SND_ASYNC);break;
	case 2: SoundStatus = PlaySoundA("sound\\zvuk_v_vagone.wav", NULL, SND_ASYNC);break;
	case 3: SoundStatus = PlaySoundA("sound\\zvuk_metro2.wav", NULL, SND_ASYNC);	break;
	case 4: SoundStatus = PlaySoundA("sound\\zvuk_metro.wav", NULL,SND_ASYNC);break;	
	case 5: SoundStatus = PlaySoundA("sound\\perehod_na_liniyu_2.wav", NULL, SND_ASYNC);break;
	case 6: SoundStatus = PlaySoundA("sound\\ostorojno_dveri_zakrsya2.wav", NULL, SND_ASYNC);break;
	case 7: SoundStatus = PlaySoundA("sound\\metro1_new.wav", NULL, SND_ASYNC);break;
	}
	if(SoundStatus == 1)
	{
		GotoXY(0,0);
		cout << "SoundStatus OK";
	}
	else
	{
		GotoXY(0,0);
		cout << "SoundStatus BAD";
	}
	return 1;
}
DWORD WINAPI Train1(void*p) //запускает несколько поездов на разных направлениях
{
	while(1)
	{	
		SubWay::ShowTrain(25,0,200);
		SubWay::ShowTrain(35,0,200);
		SubWay::ShowTrain(36,0,200);
	}
}
DWORD WINAPI Train2(void*p)
{
	while(1)
	{
		SubWay::ShowTrain(26,15,200);
		SubWay::ShowTrain(36,0,200);
		SubWay::ShowTrain(35,10,200);
	}
}
DWORD WINAPI Train3(void*p)
{
	while(1)
	{
		SubWay::ShowTrain(35,15,200);
		SubWay::ShowTrain(26,0,200);
		SubWay::ShowTrain(25,10,200);
	}
}
DWORD WINAPI Train4(void*p)
{
	while(1)
	{
		SubWay::ShowTrain(36,15,200);
		SubWay::ShowTrain(25,0,200);
		SubWay::ShowTrain(26,10,200);
	}
}
////////////////////Потоки Moldovich end/////////////////////

_city::_city(mapElt** MAP, mapElt** METRO, int WIDTH, int HEIGHT, int maxX, int maxY, int begX, int begY, bool metro)
{
	this->MAP = MAP;
	this->METRO = METRO;
	this->WIDTH = WIDTH;
	this->HEIGHT = HEIGHT;
	this->begX = begX;
	this->begY = begY;
	this->maxX = maxX;
	this->maxY = maxY;
	curNulX = 29;
	curNulY = 40;
	this->metro = metro;
	needToRef = false;
	curX = curNulX;
	curY = curNulY;
	ShowedInterf = true;
	if (!metro)
	{
		curChar = MAP[curNulX][curNulY].getSym ();
		curColor = MAP[curNulX][curNulY].getColor ();
		curColor += 16;
		curAuthor = new char [strlen (MAP[curNulX][curNulY].getAuthor ())+1];
		curDescr = new char [strlen (MAP[curNulX][curNulY].getDescription ())+1];
		strcpy (curAuthor, MAP[curNulX][curNulY].getAuthor ());
		strcpy (curDescr, MAP[curNulX][curNulY].getDescription ());
		MAP[curNulX][curNulY].setAll (curChar, curColor, curAuthor, curDescr);
	}
	else
	{
		curChar = METRO[curNulX][curNulY].getSym ();
		curColor = METRO[curNulX][curNulY].getColor ();
		curColor += 16;
		curAuthor = new char [strlen (METRO[curNulX][curNulY].getAuthor ())+1];
		curDescr = new char [strlen (METRO[curNulX][curNulY].getDescription ())+1];
		strcpy (curAuthor, METRO[curNulX][curNulY].getAuthor ());
		strcpy (curDescr, METRO[curNulX][curNulY].getDescription ());
		METRO[curNulX][curNulY].setAll (curChar, curColor, curAuthor, curDescr);
	}
}



void _city::swtch (void)
{
	needToRef = true;
	metro = !metro;
	if (!metro)
	{
		curChar = MAP[curX][curY].getSym ();
		curColor = MAP[curX][curY].getColor ();
		delete [] curAuthor;
		delete [] curDescr;
		curAuthor = new char [strlen(MAP[curX][curY].getAuthor ())+1];
		curDescr = new char [strlen(MAP[curX][curY].getDescription ())+1];
		strcpy (curAuthor, MAP[curX][curY].getAuthor ());
		strcpy (curDescr, MAP[curX][curY].getDescription ());
		MAP[curX][curY].setAll (curChar, curColor+16, curAuthor, curDescr);
	}
	else
	{
		metro = metro;
		while(!_kbhit())
		{
			/*curChar = METRO[curX][curY].getSym ();
			curColor = METRO[curX][curY].getColor ();
			delete [] curAuthor;
			delete [] curDescr;
			curAuthor = new char [strlen(METRO[curX][curY].getAuthor ())+1];
			curDescr = new char [strlen(METRO[curX][curY].getDescription ())+1];
			strcpy (curAuthor, METRO[curX][curY].getAuthor ());
			strcpy (curDescr, METRO[curX][curY].getDescription ());
			METRO[curX][curY].setAll (curChar, curColor+16, curAuthor, curDescr);*/

			system("mode con cols=200 lines=250");

			//SubWay Sub2; // создаём объект-2 класса SubWay

			ClearScreen();


			Draw_Subway(); //объеденил всё что статически рисуется в метро

			//----------Поезда(потоки)---------//
			if(flag_suspended == 0)
			{
				hThreadSound_Metro = CreateThread(0,0,Sound_Metro,0,THREAD_SUSPEND_RESUME,0);
				hThreadTrain1 = CreateThread(0,0,Train1,0,THREAD_SUSPEND_RESUME,0);
				hThreadTrain2 = CreateThread(0,0,Train2,0,THREAD_SUSPEND_RESUME,0);
				hThreadTrain3 = CreateThread(0,0,Train3,0,THREAD_SUSPEND_RESUME,0);
				hThreadTrain4 = CreateThread(0,0,Train4,0,THREAD_SUSPEND_RESUME,0);
			}
			else 
			{
				hThreadSound_Metro = CreateThread(0,0,Sound_Metro,0,THREAD_SUSPEND_RESUME,0);
				ResumeThread(hThreadTrain1);
				ResumeThread(hThreadTrain2);
				ResumeThread(hThreadTrain3);
				ResumeThread(hThreadTrain4);
			}

			system("title Город v 1.3.0: Метро");

			int key = 0;
			key = _getch();
			if ((key == Tab) || (key == 27))
			{

				++flag_suspended;
				SuspendThread(hThreadTrain1);
				SuspendThread(hThreadTrain2);
				SuspendThread(hThreadTrain3);
				SuspendThread(hThreadTrain4);
				PlaySoundA(" ", 0, 0); // такой вызов прекращает все воспроизводимые wave потоки

				ClearScreen();
				metro = !metro;
				system("mode con cols=140 lines=55");
				ShowedInterf = false;
				//_city::swtch();
				//_city::show ();



			}
			

			break;
		}


	}
}

_city::~_city(void)
{
	delete [] curAuthor;
	delete [] curDescr;
}

void _city::show (void)
{
	COORD c;
	DWORD Dummy;
	WORD Attrib;
	char sym;
	CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
	GetConsoleScreenBufferInfo(h, &csbiInfo);

	for (int i = 0; i < WIDTH; i ++)
		for (int j = 0; j < HEIGHT; j++)
		{
			if (!metro)
			{
				if ((MAP[curNulX+i][curNulY+j].isChanged ()) || (needToRef))
				{
					c.X = begX + i;
					c.Y = begY + j;
					char sym = MAP[curNulX+i][curNulY+j].getSym ();
					SetConsoleTextAttribute (h, MAP[curNulX+i][curNulY+j].getColor ());
					SetConsoleCursorPosition (h, c);
					cout << MAP[curNulX+i][curNulY+j].getSym ();
					MAP[curNulX+i][curNulY+j].showed ();
					/*	Attrib = MAP[curNulX+i][curNulY+j].getColor ();
					WriteConsoleOutputCharacterA (h, &sym, 1, c, &Dummy);
					WriteConsoleOutputAttribute (h, &Attrib, 1, c, &Dummy);*/

				}
			}

			else
			{
				if ((METRO[curNulX+i][curNulY+j].isChanged ()) || (needToRef))
				{
					c.X = begX + i;
					c.Y = begY + j;
					sym = METRO[curNulX+i][curNulY+j].getSym ();
					//MultiByteToWideChar (CP_UTF7, 0, &smb, -1, &sym, 1);
					//Attrib = METRO[curNulX+i][curNulY+j].getColor ();
					//WriteConsoleOutputCharacterA (h, &sym, 1, c, &Dummy);
					//WriteConsoleOutputAttribute (h, &Attrib, 1, c, &Dummy);
					SetConsoleTextAttribute (h, METRO[curNulX+i][curNulY+j].getColor ());
					SetConsoleCursorPosition (h, c);
					cout << METRO[curNulX+i][curNulY+j].getSym ();
					METRO[curNulX+i][curNulY+j].showed ();
				}
			}
		}

		needToRef = false;

		if (!ShowedInterf)
		{
			SetConsoleTextAttribute (h, 15);
			Interface ();
			ShowedInterf = true;
			needToRef = true;
			
		}

		
}

void _city::moveMap (int direct, bool tabbed)
{
	if ((direct == RIGHT) && (curNulX > 0) && (!tabbed)) 
	{
		curNulX--;
	}
	else if ((direct == LEFT) && (curNulX + WIDTH + 1< maxX) && (!tabbed)) 
	{
		curNulX++;
	}
	else if ((direct == UP) && (curNulY > 0) && (!tabbed)) 
	{
		curNulY--;
	}
	else if ((direct == DOWN) && (curNulY + HEIGHT + 1 < maxY) && (!tabbed)) 
	{
		curNulY++;
	}
	else if ((direct == RIGHT) && (tabbed))
	{
		if (curNulX > 10) curNulX-=10;
		else curNulX = 0;
		if (curX > curNulX + WIDTH - 1) setCur (curNulX + WIDTH - 1, curY);
	}
	else if ((direct == LEFT) && (tabbed))
	{
		if (curNulX + WIDTH + 10 < maxX) curNulX+=10;
		else curNulX = maxX - WIDTH;
		if (curX < curNulX) setCur (curNulX, curY);
	}
	else if ((direct == UP) && (tabbed))
	{
		if (curNulY > 10) curNulY-=10;
		else curNulY = 0;
		if (curY > curNulY + HEIGHT - 1) setCur (curX, curNulY + HEIGHT - 1);
	}
	else if ((direct == DOWN) && (tabbed))
	{
		if (curNulY + HEIGHT + 10 < maxY) curNulY+=10;
		else curNulY = maxY - HEIGHT;
		if (curY < curNulY) setCur (curX, curNulY);
	}
	else if ((direct == 00) && (tabbed))
	{
		curNulX = 0;
		curNulY = 0;
		curX = 0;
		curY = 0;
		setCur (curX, curY);
	}
	else if ((direct == 10) && (tabbed))
	{
		curNulX = maxX - WIDTH - 1;
		curNulY = 0;
		curX = maxX-1;
		curY = 0;
		setCur (curX, curY);
	}
	else if ((direct == 01) && (tabbed))
	{
		curNulX = 0;
		curNulY = maxY - HEIGHT - 1;
		curX = 0;
		curY = maxY - 1;
		setCur (curX, curY);
	}
	else if ((direct == 11) && (tabbed))
	{
		curNulX = maxX - WIDTH;
		curNulY = maxY - HEIGHT;
		curX = maxX - 1;
		curY = maxY - 1;
		setCur (curX, curY);
	}
	needToRef = true;
}

void _city::setCur (int X, int Y)
{
	if (!metro)
	{
		MAP[curX][curY].setAll (curChar, curColor-16, curAuthor, curDescr);
		curX = X;
		curY = Y;
		curChar = MAP[curX][curY].getSym ();
		curColor = MAP[curX][curY].getColor ();
		curColor += 16;
		delete [] curAuthor;
		delete [] curDescr;
		curAuthor = new char [strlen (MAP[curX][curY].getAuthor ())+1];
		curDescr = new char [strlen (MAP[curX][curY].getDescription ())+1];
		strcpy (curAuthor, MAP[curX][curY].getAuthor ());
		strcpy (curDescr, MAP[curX][curY].getDescription ());
		MAP[curX][curY].setAll (curChar, curColor, curAuthor, curDescr);
	}
	else
	{
		METRO[curX][curY].setAll (curChar, curColor-16, curAuthor, curDescr);
		curX = X;
		curY = Y;
		curChar = METRO[curX][curY].getSym ();
		curColor = METRO[curX][curY].getColor ();
		curColor += 16;
		delete [] curAuthor;
		delete [] curDescr;
		curAuthor = new char [strlen (METRO[curX][curY].getAuthor ())+1];
		curDescr = new char [strlen (METRO[curX][curY].getDescription ())+1];
		strcpy (curAuthor, METRO[curX][curY].getAuthor ());
		strcpy (curDescr, METRO[curX][curY].getDescription ());
		METRO[curX][curY].setAll (curChar, curColor, curAuthor, curDescr);
	}


}

void _city::curRef (int direct)
{
	if (!metro)
	{
		if (curChar == (char) 1) curChar = ' ';
		if (direct == LEFT) MAP[curX-1][curY].setAll (curChar, curColor-16, curAuthor, curDescr);
		else if (direct == RIGHT) MAP[curX+1][curY].setAll (curChar, curColor-16, curAuthor, curDescr);
		else if (direct == UP) MAP[curX][curY+1].setAll (curChar, curColor-16, curAuthor, curDescr);
		else if (direct == DOWN) MAP[curX][curY-1].setAll (curChar, curColor-16, curAuthor, curDescr);
		curChar = MAP[curX][curY].getSym ();
		curColor = MAP[curX][curY].getColor ();
		curColor += 16;
		delete [] curAuthor;
		delete [] curDescr;
		curAuthor = new char [strlen (MAP[curX][curY].getAuthor ())+1];
		curDescr = new char [strlen (MAP[curX][curY].getDescription ())+1];
		strcpy (curAuthor, MAP[curX][curY].getAuthor ());
		strcpy (curDescr, MAP[curX][curY].getDescription ());
		MAP[curX][curY].setAll (curChar, curColor, curAuthor, curDescr);
	}
	else
	{
		if (direct == LEFT) METRO[curX-1][curY].setAll (curChar, curColor-16, curAuthor, curDescr);
		else if (direct == RIGHT) METRO[curX+1][curY].setAll (curChar, curColor-16, curAuthor, curDescr);
		else if (direct == UP) METRO[curX][curY+1].setAll (curChar, curColor-16, curAuthor, curDescr);
		else if (direct == DOWN) METRO[curX][curY-1].setAll (curChar, curColor-16, curAuthor, curDescr);
		curChar = METRO[curX][curY].getSym ();
		curColor = METRO[curX][curY].getColor ();
		curColor += 16;
		delete [] curAuthor;
		delete [] curDescr;
		curAuthor = new char [strlen (METRO[curX][curY].getAuthor ())+1];
		curDescr = new char [strlen (METRO[curX][curY].getDescription ())+1];
		strcpy (curAuthor, METRO[curX][curY].getAuthor ());
		strcpy (curDescr, METRO[curX][curY].getDescription ());
		METRO[curX][curY].setAll (curChar, curColor, curAuthor, curDescr);
	}
}

void _city::moveCur (int direct)
{
	if ((direct == LEFT) && (curX < curNulX+WIDTH-1))
	{
		curX++;
		curRef (LEFT);
	}
	else if ((direct == LEFT) && (curX == curNulX+WIDTH-1) && (curX < maxX-2))
	{
		curX++;
		curRef (LEFT);
		moveMap (LEFT, false);
	}
	else if ((direct == RIGHT) && (curX > curNulX))
	{
		curX--;
		curRef (RIGHT);
	}
	else if ((direct == RIGHT) && (curX == curNulX) && (curNulX > 0))
	{
		curX--;
		curRef (RIGHT);
		moveMap (RIGHT, false);
	}
	else if ((direct == UP) && (curY > curNulY))
	{
		curY--;
		curRef (UP);
	}
	else if ((direct == UP) && (curY == curNulY) && (curNulY > 0))
	{
		curY--;
		curRef (UP);
		moveMap (UP, false);
	}
	else if ((direct == DOWN) && (curY < curNulY + HEIGHT - 1))
	{
		curY++;
		curRef (DOWN);
	}
	else if ((direct == DOWN) && (curY == curNulY + HEIGHT - 1) && (curY < maxY - 2))
	{
		curY++;
		curRef (DOWN);
		moveMap (DOWN, false);
	}
}

void _city::showInfo (void)
{
	COORD c;
	c.X = 0;
	c.Y = 45;
	SetConsoleTextAttribute (h, 15);
	SetConsoleCursorPosition (h, c);
	cout << "                                                                                                      ";
	SetConsoleCursorPosition (h, c);
	cout << curDescr;
	c.Y = 47;
	SetConsoleCursorPosition (h, c);
	cout << "                                                                                                      ";
	SetConsoleCursorPosition (h, c);
	cout << curAuthor;
	/*c.Y = 48;
	SetConsoleCursorPosition (h, c);
	cout << "                                                                                                      ";
	SetConsoleCursorPosition (h, c);
	cout << "X: " << curX << " || Y: " << curY << " || Symbol: \"" << curChar << "\"|| Color: " << curColor;*/
}

bool _city::isMetro (void)
{
	return metro;
}